% input parent: the parent vector
% input N: the search space dimensionality
% input sigma: mutation strength
% input sigmaStop: sigma stop for termination condition
% input test_func: the function to test against
% input d:
% output parent: the optimum vector
% output sigma_dyn: sigma dynamics
% output fitness_dyn: fitness dynamics
% output generations: the generations
function [parent, sigma_dyn, fitness_dyn, generations] = one_plus_one_es(parent, N, sigma, sigmaStop, test_func, d)

%initialization (line 1)
randn("state", 7);

% 1/5 Rule adaptions
pOpt = 0.2;
alpha = 1.2;
G = N;

% determine initial parent fitness (line 2)
parent_fitness = feval(test_func, parent, d, N);

% generation counter (line 3)
g = 0;

% sigma, generation and fitness log for plotting
sigma_dyn(g+1) = [sigma];
generations(g+1) = [g];
fitness_dyn(g+1) = [parent_fitness];

% evolution loop (line 4)
while(sigma > sigmaStop)
	% count successfull mutations in G
	ns = 0;
	
	% mutation loop with constant sigma
	for k=1:G
		% calculate offsprings (line 5-6)
		offspring = parent + sigma * randn(N, 1);
		offspring_fitness = feval(test_func, offspring, d, N);
	
		% minimization (line 7-10)
		if(offspring_fitness <= parent_fitness)
			parent = offspring;
			parent_fitness = offspring_fitness;
			ns = ns + 1; % successful mutation counter
		endif
	
		% generation increase (line 11)
		g = g+1;
		
		% add the plot values
		sigma_dyn(g) = [sigma];
		generations(g) = [g];
		fitness_dyn(g) = [parent_fitness];
	endfor
	
	ps = ns / G;
	if(ps > pOpt)
		sigma = sigma * alpha;
	elseif(ps < pOpt)
		sigma = sigma / alpha;
	endif
endwhile

endfunction